#include "udp_punchthrough.hpp"  // 引入 UDP 打洞头文件
#include <asio.hpp>  // 引入 ASIO 库
#include <iostream>  // 引入输入输出流

using asio::ip::udp;  // 使用 UDP 协议

// 构造函数：初始化 UDP 套接字和目标地址
UDPPunchthroughClient::UDPPunchthroughClient(asio::io_context& io_context, const std::string& target_ip, unsigned short target_port)
    : io_context_(io_context), socket_(io_context, udp::endpoint(udp::v4(), 0)) {
    target_endpoint_ = udp::endpoint(asio::ip::address::from_string(target_ip), target_port);
    local_endpoint_ = socket_.local_endpoint();  // 获取本地端点
}

// 开始 UDP 打洞过程
void UDPPunchthroughClient::start() {
    std::cout << "Starting UDP punchthrough to " << target_endpoint_ << std::endl;

    // 发送第一个打洞请求
    send_punch();

    // 接收 B 的回应
    receive_response();
}

// 发送 UDP 打洞请求
void UDPPunchthroughClient::send_punch() {
    std::string message = "UDP Hole Punch Request";  // 打洞请求的消息内容

    // 发送消息到目标 B
    socket_.send_to(asio::buffer(message), target_endpoint_);

    std::cout << "Sent punchthrough request to " << target_endpoint_ << std::endl;
}

// 接收 B 的回应
void UDPPunchthroughClient::receive_response() {
    char buffer[1024];  // 接收数据的缓冲区
    udp::endpoint sender_endpoint;

    // 等待接收 B 的回应
    size_t len = socket_.receive_from(asio::buffer(buffer), sender_endpoint);

    std::cout << "Received response from " << sender_endpoint << ": " << std::string(buffer, len) << std::endl;

    // 检查回应内容，如果是打洞成功的回应
    if (std::string(buffer, len) == "UDP Hole Punch Response") {
        std::cout << "Successfully punched through NAT! Direct connection established." << std::endl;
    } else {
        std::cerr << "Failed to establish direct connection!" << std::endl;
    }
}
